// src/main/java/swb/api/com/service/impl/UserServiceImpl.java
package swb.api.com.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import swb.api.com.common.exception.SwbException;
import swb.api.com.repository.SysUserRepository;
import swb.api.com.repository.SysUserRoleRepository;
import swb.api.com.repository.UserInfoRepository;
import swb.api.com.repository.dto.SysUser;
import swb.api.com.repository.dto.SysUserRole;
import swb.api.com.repository.dto.UserInfo;
import swb.api.com.service.SmsService;
import swb.api.com.service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import swb.api.com.vo.req.AdminCreateRequest;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Optional;

/**
 * 用户服务实现类
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserInfoRepository userInfoRepository;
    @Autowired
    private SysUserRoleRepository sysUserRoleRepository;
    @Autowired
    private SysUserRepository sysUserRepository;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Value("${wechat.appid}")
    private String wechatAppid;

    @Value("${wechat.secret}")
    private String wechatSecret;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private SmsService smsService;

    @Override
    public UserInfo wechatLogin(String code) throws Exception {
        // 1. 调用微信接口获取openid
        String url = String.format(
                "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                wechatAppid, wechatSecret, code
        );

        String response = restTemplate.getForObject(url, String.class);
        log.info("微信登录响应: {}", response);
        Map<String, Object> resultMap = objectMapper.readValue(response, Map.class);

        if (resultMap.containsKey("errcode")) {
            log.error("微信登录失败: {}", response);
            throw new Exception("微信登录失败");
        }

        String openid = (String) resultMap.get("openid");
        String unionid = (String) resultMap.get("unionid");

        // 2. 查询用户是否存在
        UserInfo userInfo = userInfoRepository.findByOpenid(openid).orElse(null);
        // 3. 如果用户不存在，则创建新用户
        if (userInfo == null) {
            userInfo = new UserInfo();
            userInfo.setOpenid(openid);
            userInfo.setUnionid(unionid);
            userInfo.setStatus(1);
            userInfo.setCreatedTime(LocalDateTime.now());
            userInfo.setUpdatedTime(LocalDateTime.now());
            // 保存新用户
            userInfoRepository.save(userInfo);
        } else {
            // 更新用户信息
            userInfo.setUpdatedTime(LocalDateTime.now());
            userInfoRepository.save(userInfo);
        }

        return userInfo;
    }

    /**
     * 根据ID或openid查询用户
     *
     * @param id     用户ID
     * @param openid 用户openid
     * @return 用户信息
     */
    @Override
    public UserInfo findUserByIdOrOpenidOrMobile(Long id, String openid, String mobile) {
        if (id != null) {
            return userInfoRepository.findById(id)
                    .orElseThrow(() -> new SwbException("用户不存在"));
        } else if (StringUtils.hasText(openid)) {
            return userInfoRepository.findByOpenid(openid)
                    .orElseThrow(() -> new SwbException("用户不存在"));
        } else if (StringUtils.hasText(mobile)) {
            return userInfoRepository.findByMobile(mobile)
                    .orElseThrow(() -> new SwbException("用户不存在"));
        } else {
            throw new SwbException("必须提供id或openid或mobile参数");
        }
    }

    @Override
    @Transactional
    public UserInfo bindMobile(Long userId, String mobile) {
        // 检查手机号是否已被其他用户绑定
        Optional<UserInfo> existingUser = userInfoRepository.findByMobile(mobile);
        if (existingUser.isPresent()) {
            UserInfo user = existingUser.get();
            // 如果是同一个用户，则直接返回
            if (userId != null && user.getId().equals(userId)) {
                return user;
            }
            // 否则抛出异常
            throw new SwbException("该手机号已被其他用户绑定");
        }

        UserInfo userInfo;
        if (userId != null) {
            // 已登录用户绑定手机号
            userInfo = userInfoRepository.findById(userId)
                    .orElseThrow(() -> new SwbException("用户不存在"));
        } else {
            // 新用户直接用手机号注册
            userInfo = new UserInfo();
            userInfo.setMobile(mobile);
            userInfo.setStatus(1);
            userInfo.setCreatedTime(LocalDateTime.now());
        }

        // 更新手机号和时间
        userInfo.setMobile(mobile);
        userInfo.setUpdatedTime(LocalDateTime.now());
        return userInfoRepository.save(userInfo);
    }

    @Override
    public UserInfo smsLogin(String mobile, String code) {
        // 验证短信验证码
        boolean isValid = smsService.verifyCode(mobile, code);
        if (!isValid) {
            throw new SwbException("验证码错误或已过期");
        }

        // 查找用户是否存在
        Optional<UserInfo> existingUser = userInfoRepository.findByMobile(mobile);
        UserInfo userInfo;

        if (existingUser.isPresent()) {
            // 用户已存在，直接返回
            userInfo = existingUser.get();
            // 更新最后登录时间
            userInfo.setUpdatedTime(LocalDateTime.now());
            userInfoRepository.save(userInfo);
        } else {
            // 新用户，创建账户
            userInfo = new UserInfo();
            userInfo.setMobile(mobile);
            userInfo.setStatus(1);
            userInfo.setCreatedTime(LocalDateTime.now());
            userInfo.setUpdatedTime(LocalDateTime.now());
            userInfo = userInfoRepository.save(userInfo);
        }

        return userInfo;
    }

    @Override
    public Page<UserInfo> findAll(Pageable pageable) {
        try {
            return userInfoRepository.findAll(pageable);
        } catch (Exception e) {
            throw new RuntimeException("Failed to fetch user info list", e);
        }
    }

    @Override
    public void updateBalance(Long userId, BigDecimal newBalance) {
        UserInfo user = userInfoRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        user.setBalance(newBalance);
        userInfoRepository.save(user);
    }

    @Override
    public SysUser findByUsername(String username) {
        return sysUserRepository.findByUsername(username);
    }

    @Override
    @Transactional
    public void createAdmin(AdminCreateRequest adminCreateRequest) {
        // 检查用户名是否已存在
        if (sysUserRepository.findByUsername(adminCreateRequest.getUsername()) != null) {
            throw new RuntimeException("用户名已存在");
        }

        // 创建管理员用户
        SysUser user = new SysUser();
        user.setUsername(adminCreateRequest.getUsername());
        user.setPassword(passwordEncoder.encode(adminCreateRequest.getPassword()));
        user.setNickname(adminCreateRequest.getNickname());
        user.setEmail(adminCreateRequest.getEmail());
        user.setMobile(adminCreateRequest.getMobile());
        user.setStatus(1); // 默认启用
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        // 保存用户
        user = sysUserRepository.save(user);

        // 分配管理员角色（假设角色ID为1）
        SysUserRole userRole = new SysUserRole();
        userRole.setUserId(user.getId());
        userRole.setRoleId(1L);
        sysUserRoleRepository.save(userRole);
    }

}
